package cn.dm.serializer;

import cn.dm.pojo.User;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.runtime.RuntimeSchema;

/**
 * 介绍
 * 1) Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准，
 * 目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。
 * 2) Protocol Buffers 是一种轻便高效的结构化数据存储格式，可以用于结构化数据串行化，或者说序列化。它很适合做数据存储或 RPC 数据交换格式。
 * 可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API
 * <p>
 * 优点
 * 独立于语言，独立于平台，最重要的是它的效率相当高，用protobuf序列化后的大小是json的10分之一，xml格式的20分之一，是二进制序列化的10分之一
 * <p>
 * google原生的protobuffer使用起来相当麻烦，首先要写.proto文件，然后编译.proto文件，生成对应的.java文件。
 * protostuff基于Google Protobuf，好处就是不用自己写.proto文件同时在几乎不损耗性能的情况下即可实现对象的序列化与反序列化
 * <p>
 * 注
 * redis-jedis序列化为protobuf
 * redis-lettuce序列化为xml
 * redis-springboot序列化为json
 */
public class ProtostuffSerializer {

    Schema<User> schema = RuntimeSchema.createFrom(User.class);

    public byte[] serialize(final User user) {
        final LinkedBuffer buffer = LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE);
        try {
            return serializeInternal(user, schema, buffer);
        } catch (final Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        } finally {
            buffer.clear();
        }
    }

    public User deserialize(final byte[] bytes) {
        try {
            User user = deserializeInternal(bytes, schema.newMessage(), schema);
            return user;
        } catch (final Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    private <T> byte[] serializeInternal(final T source, final Schema<T> schema, final LinkedBuffer buffer) {
        return ProtostuffIOUtil.toByteArray(source, schema, buffer);
    }

    private <T> T deserializeInternal(final byte[] bytes, final T result, final Schema<T> schema) {
        ProtostuffIOUtil.mergeFrom(bytes, result, schema);
        return result;
    }
}
